//全局变量和定义区域
#include<stdio.h>


//代码1
//解析代码的真实性

/*
	
	本节课知识点：
	(1)指向常量的指针---常量指针(const int* p)
		语法形式：
		含义：指针指向的值是一个常量，不能通过指针修改这个值。就是实现read-only作用,只读不修改
		作用:主要用来保护数据，防止其被意外修改。
		使用规则:
		1.指针可以修改为指向不同的变量/常量<相当于一个读书卡能借不同的书，但是这个读书卡没权限修改书中的内容>
		2.可以通过解引用来访问读取指针指向的数据,即可以访问。(就是有权限访问数据)
		例如：
		int num = 520;
		const int cnum = 888;//这里是定义了一个只读的变量(说白了就是一个不可修改的常量)
		const int* pc = &cnum;//现在这个指针(不可修改)指向的是一个'常量'

		printf("cnum = %d,&cnum:%p\n", cnum, &cnum);
		printf("*pc = %d,pc = %p\n", *pc, pc);//通过解引用访问到了cnum这个常量

		pc = &num;//现在这个指针(不可修改)指向的是一个'变量'
		printf("num = %d,&num = %p\n", num, &num);
		printf("*pc = %d,pc = %p", *pc, pc);

		再例如：
		const int num = 520;
		const int* p = &num; // p是一个指向常量的指针
		printf("%d\n", *p);    // 可以访问num的值
		// *p = 1000;         // 这行代码会报错，因为不能通过p修改num的值
		int anotherNum = 1000;
		p = &anotherNum;       // p可以指向不同的变量

		3.不可以通过解引用来修改指针指向的变量(也就是无权限修改数据)
		因为const类型就是read-only(只读)


	(2)指针常量<小甲鱼课程叫常量指针，但是我查阅了来自CSDN和GitHub资料，它不叫常量指针，因为它就是一个常量>(int *const p)
		1.语法形式：
		2.含义： 指针自身是常量，不能再指向其他地址。<把指针看做成一个钥匙，把它指向的变量看做保险柜，这个钥匙有对应的保险柜，保险柜放什么都可以，但是这个钥匙只能开这个保险柜>
		3.作用：固定指针的指向,强制指针始终指向某个内存地址，防止意外修改指向
		使用法则：
		1.指针不能修改为指向不同的变量或常量。
		2.可以通过解引用来访问和修改指针指向的数据。
		int num = 520;
		int* const p = &num;   // p是一个常量指针，指向num
		printf("%d\n", *p);    // 可以访问num的值
		*p = 1000;             // 可以修改num的值
		// int anotherNum = 1000;
		// p = &anotherNum;   // 这行代码会报错，因为不能让p指向其他变量

	指针常量 VS 常量指针

	类型					语法					指针指向是否可变				指向的数据是否可修改
	指针常量				int* const				×不可变						√可修改	
	常量指针				const int*				√可变						×不修改


	(3)指向'指向常量的指针'的指针（const int** q）
		1.语法形式：q 是一个二级指针，指向一个const int *类型的指针，被指向的指针（const int*）本身可以通过修改指向的地址，但是不能通过它修改所指的常量数据
		2.关键特性：通过 q 可以修改其指向的一级指针(p)也就是可以换指向对象和指向常量的指针用法一样;但是不能通过解引用修改常量的数据，也就是不能**q = 888;**q只有可读权限; 
		3.作用：允许间接修改指向常量的指针的地址，同时保护常量的不可变性，常用于函数参数传递和多维常量数据结构操作
		例如:
		int num = 520;
		const int* p = &num;
		const  int** q = &p;
		printf("%d\n", **q);

	(4)指向'指向常量指针'的常指针(const int * const *p)
		1.特点：指针指向不可修改，指针指向的值也不可以修改<专门专用，最高级保护>
		
		const int num = 520;
		const int * const p = &num;
		const int * const *q = &p;
		//注意哈，const 永远限制紧随着它的标识符。const int * const *q = &p; 相当于 (const int) * (const *q) = &p;
		//即第一个 const 限制的是 **q 的指向，第二个 const 限制的是 *q 的指向，唯有一个漏网之鱼 —— q 没有被限制




	以上就是本节课知识点Ｏ(≧▽≦)Ｏ，如果你还不知道的话就看看这个文章： https://blog.csdn.net/as480133937/article/details/120804503
*/
void work1()
{
	//A：
	const int numA = 520;
	int* pA = &numA;
	//在VS中报错类型显示"const int* 类型的值不能初始化为int* 类型的实体",说人话就是这里的类型不一致,你程序现在可能不显示那是因为我将文件类型改为了.c类型（C语言程序),我们就是推荐使用.cpp类型，因为是程序规则更加严格
	// num是一个常量，其地址被分配给一个非const的指针p，这会导致尝试修改常量的风险。就是可以通过指针修改这个常量,const这个保护就没有作用啦
	
	//B：
	int numB = 520;
	const int* pB = &numB;
	//定义了一个指向常量的指针，符合使用规则1

	//C:
	const int numC = 520;
	const int* pC = &numC;
	//定义了一个read-only变量，同时定义了一个指向const常量的指针，符合规则。

	//D:
	const int numD = 520;
	const int* const pD = &numD;
	//定义了一个指向常量的常量指针，不可通过指针改变指针所指向的值，也不可以改变指针指向

}

//程序1
//补充第五题代码
void test1()
{
	int num = 520;
	const int* p = &num;//指向常量的指针
	const  int** q = &p;//一个指向'指向常量的指针'的指针,类型const int* 
	printf("%d\n", **q);

}

//主程序
int main()
{
	test1();
	return 0;
}